home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
util
/
misc
/
fonewd.lha
/
phonewrd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-02
|
22KB
|
922 lines
/*
Phonewrd - given a phone number, find all words or phrases in a dictionary
which fit it.
version 1.1 - 4/5/93
Ported To Amiga.
Christopher Klaus, cklaus@hotsun.nersc.gov or gt6468c@hydra.gatech.edu
26468 GaTech Station
Atlanta, GA 30332
(404)-676-9622
(c) copyright 1993, Eric Haines, all rights reserved (erich@eye.com)
See the man page for details.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*============= default related =========================================== */
/* path to dictionary */
#define DICT_PATH "dict"
/* number of digits in phone number */
#define NUM_DIGITS 7
/* how many numerals are allowed in our phrase? */
#define NUMERALS_ALLOWED 0
/* minimum length of words: note that 1 always gets bumped to 2, because of
* OneLetter below.
*/
#define MIN_LENGTH 1
/* one letter words that are acceptable */
#define ONE_LETTER "aio"
/* If you like things like "CDB" (see the bee) or "IM4U, use or modify the
* array below. Yes, "j" and "k" are potential names, "m" is only in "I am",
* "q" is queue, etc - you decide... This option tends to generate lots of
* useless goop, but it's good if you're desperate.
*/
/* #define ONE_LETTER "abcdgimoptuxy248" */
#define NO_NUMBER -2
/* to make Q and Z not be anything, set them to NO_NUMBER, else set them
* to the digit you want (e.g. 0 or 1)
*/
#define Q NO_NUMBER
#define Z NO_NUMBER
/* translation table for letters to numbers */
int Letter2Numeral[] =
/* a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z */
{ 2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,Q,7,7,8,8,8,9,9,9,Z } ;
/*============= storage space related ===================================== */
#define MAX_DIGITS 14
#define MAX_INDICES (((MAX_DIGITS+1)*MAX_DIGITS)/2)
/* increment for word list memory space */
#define WORD_LIST_SIZE 50
/*============= internal use constants ==================================== */
#define FIXED_LETTER -1
#define BUFSIZE 256
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
/*============= structures ================================================ */
/* array of words, indexed by digit location and length of word. This list is
* built up in the first part of the program, as each dictionary word is
* categorized and put in its list. Then this structure is traversed to make
* up the combinations.
*/
typedef struct {
char **p_word ; /* list of pointers to words */
int count ; /* current count */
int size ; /* allocated size */
} wordlist, *p_wordlist ;
/*============= data and macros =========================================== */
#define IndexWL( digit_loc, length ) ( WLoffset[digit_loc] + length - 1 )
wordlist WL[MAX_INDICES] ;
int WLoffset[MAX_DIGITS] ;
int PhoneNum[MAX_DIGITS+1] ; /* phone number translation */
char PhoneStr[MAX_DIGITS+1] ; /* phone number letter, if specified */
int NumeralMapped[10] ; /* if TRUE, then index # is mapped */
char OneLetter[BUFSIZE] ;
char DictPath[BUFSIZE] ;
char *ProgName ;
int NumDigits ;
int NumIndices ;
int NumNumerals ;
int MinLength ;
int RollOwn ;
int Concat ;
int Verbose ;
int MatchTot ;
int Wildcard ;
int TotBrk ;
int HoldSize ;
int HoldCount ;
char **HoldWord ;
char OutputGrid[MAX_DIGITS][27] ;
#define USAGE fprintf( stderr, "usage: %s [options] phone#[*...]\n" \
" [*...] - extra *'s at the end mean optional wildcard letters\n" \
" -l # - minimum length of words (cur. == %d)\n" \
" -n # - number of numerals allowed in phrase (cur. == %d)\n" \
" -q # - mapping of q (cur. == %d)\n" \
" -z # - mapping of z (cur. == %d)\n" \
" -d string - dictionary path (cur. == %s)\n" \
" -s string - allowed single letter words (cur. == \"%s\")\n" \
" -m char[26] - mapping of entire alphabet\n" \
" -r - output the corresponding letters in an array\n" \
" -c - output all combinations (no dictionary)\n" \
" -v - verbose output (show words that do fit)\n" \
, ProgName \
, MinLength \
, NumNumerals \
, Q \
, Z \
, DictPath \
, OneLetter \
) ;
/*============= procedure declarations ==================================== */
int phone_check() ;
void roll_own() ;
void concat_it() ;
void concat_letter_out() ;
void concat_letter_breaks_out() ;
void init_wl() ;
int fit_word() ;
void search_for_match() ;
void hold_word() ;
void store_word() ;
void free_wl() ;
int scan_options() ;
/*============= procedures ================================================ */
main(argc,argv)
int argc; char *argv[];
{
int nargc ;
char *nargv[BUFSIZE], *targv ;
int i, hdr_out ;
ProgName = argv[1] ;
HoldSize = HoldCount = 0 ;
NumNumerals = NUMERALS_ALLOWED ;
MinLength = MIN_LENGTH ;
RollOwn = FALSE ;
Concat = 0 ;
Verbose = FALSE ;
strcpy( OneLetter, ONE_LETTER ) ;
strcpy( DictPath, DICT_PATH ) ;
/* translate phone number */
if ( argc < 2 ) {
fprintf( stderr, "Not enough arguments.\n" ) ;
USAGE ;
return( 1 ) ;
}
if ( !scan_options( argc, argv, &nargc, nargv ) ) {
return( 1 ) ;
}
if ( nargc < 1 ) {
fprintf( stderr, "No phone number found.\n" ) ;
USAGE ;
return( 1 ) ;
}
/* loop through phone number(s), output headers if more than one */
hdr_out = ( nargc > 1 ) ;
for ( i = 0 ; i < nargc ; i++ ) {
if ( i ) {
/* output carriage returns before 2nd, 3rd, etc */
fprintf( stdout, "\n" ) ;
}
targv = nargv[i] ;
if ( hdr_out ) {
fprintf( stdout, "# %s\n", targv ) ;
}
if ( phone_check( targv ) ) {
/* something very bad happened, so quit */
return( 1 ) ;
}
}
return( 0 ) ;
}
int
phone_check( numeral_string )
char *numeral_string ;
{
int i, tot, word_count, length, min_length, found_digit, val ;
char tchr, *tstr ;
char dict_word[BUFSIZE] ;
char out_string[BUFSIZE] ;
p_wordlist p_wl ;
FILE *infile ;
NumDigits = 0 ;
TotBrk = -1 ;
tstr = numeral_string ;
tchr = *tstr++ ;
found_digit = FALSE ;
while ( tchr != '\0' && tchr != '*' && (NumDigits <= MAX_DIGITS ) ) {
if ( ( tchr >= '0' ) && ( tchr <= '9' ) ) {
/* convert to digit */
PhoneNum[NumDigits] = (int)(tchr - '0') ;
PhoneStr[NumDigits++] = tchr ;
found_digit = TRUE ;
} else if ( ( (tchr >= 'A') && (tchr <= 'Z') ) ||
( (tchr >= 'a') && (tchr <= 'z') ) ) {
PhoneNum[NumDigits] = FIXED_LETTER ;
PhoneStr[NumDigits++] = tolower( tchr ) ;
}
tchr = *tstr++ ;
}
PhoneStr[NumDigits]='\0' ;
if ( NumDigits <= 0 ) {
fprintf( stderr, "Sorry, no digits input in `%s'\n", numeral_string ) ;
fprintf( stderr, "Recompile with a higher MAX_DIGITS setting.\n" ) ;
USAGE ;
return(0) ;
}
/* check if we're in roll own mode */
if ( RollOwn ) {
roll_own() ;
return(0) ;
}
/* check if we're in concat output mode */
if ( Concat ) {
concat_it() ;
return(0) ;
}
/* check if any numbers were input */
if ( !found_digit ) {
/* entirely alphabetic input, so translate to number */
for ( i = 0 ; i < NumDigits ; i++ ) {
val = Letter2Numeral[PhoneStr[i]-'a'] ;
if ( val != NO_NUMBER ) {
fprintf( stdout, "%d", val ) ;
} else {
fprintf( stdout, "*" ) ;
}
}
fprintf( stdout, "\n" ) ;
return(0) ;
}
if ( tchr == '*' ) {
/* the phone number ends in a wild card - phrases can be longer */
Wildcard = 1 ;
while ( *tstr++ == '*' ) {
Wildcard++ ;
}
} else {
Wildcard = 0 ;
}
if ( NumDigits > MAX_DIGITS ) {
fprintf( stderr, "Sorry, too many digits input in `%s'; "
"only %d allowed.\n", numeral_string, NumDigits ) ;
USAGE ;
return(0) ;
}
/* set up offset array for indexing WL */
tot = 0 ;
for ( i = 0 ; i < NumDigits ; i++ ) {
WLoffset[i] = tot ;
tot += (NumDigits-i) ;
}
NumIndices = ((NumDigits+1)*NumDigits)/2 ;
/* build WL */
word_count = 0 ;
init_wl() ;
infile = fopen( DictPath, "r") ;
min_length = MinLength > 1 ? MinLength : 2 ;
if ( infile != NULL ) {
while ( fgets( dict_word, BUFSIZE, infile ) ) {
word_count += fit_word( dict_word, min_length ) ;
}
} else {
fprintf( stderr, "Sorry, couldn't find dictionary at `%s'.\n",
DictPath ) ;
return(1) ;
}
fclose( infile ) ;
if ( Verbose ) {
for ( i = 0 ; i < NumDigits ; i++ ) {
for ( length = 1 ; length <= NumDigits-i ; length++ ) {
p_wl = &WL[IndexWL( i, length )] ;
if ( p_wl->count ) {
fprintf( stdout, "\nDigit %d, length %d:\n", i+1, length ) ;
for ( tot = 0 ; tot < p_wl->count ; tot++ ) {
fprintf( stdout, " %s\n", p_wl->p_word[tot] ) ;
}
}
}
}
}
MatchTot = 0 ; /* number of words matched */
/* search through WL for paths */
if ( word_count ) {
/* good, there's something to work with: search away! */
*out_string = '\0' ;
search_for_match( 0, out_string, out_string, 0 ) ;
if ( !MatchTot ) {
fprintf( stderr,
"Bad luck: dictionary words fit, but there's too much "
"numeral goop.\n" ) ;
fprintf( stderr,
"I'd try again with the option `-n %d' or so.\n",
NumNumerals+1 ) ;
}
} else {
fprintf( stderr,
"Worst luck: no dictionary words fit anywhere in %s.\n",
PhoneStr ) ;
fprintf( stderr,
"Maybe try again with the option `-s abcdgimoptuxy248'.\n" ) ;
}
free_wl() ;
return(0) ;
}
void
roll_own()
{
int digit_letter[MAX_DIGITS], found_one, search, i, j, k ;
for ( i = 0 ; i < NumDigits ; i++ ) {
if ( PhoneNum[i] == FIXED_LETTER ) {
digit_letter[i] = -2 ;
} else {
digit_letter[i] = -1 ;
}
}
found_one = TRUE ;
for ( i = 0 ; i < 26 && found_one ; i++ ) {
found_one = FALSE ;
for ( j = 0 ; j < NumDigits ; j++ ) {
if ( digit_letter[j] >= 26 ) {
/* done with this one */
fprintf( stdout, " " ) ;
} else {
if ( digit_letter[j] == -2 ) {
found_one = TRUE ;
digit_letter[j] = 26 ;
fprintf( stdout, " %c", PhoneStr[j] ) ;
} else {
for ( k = digit_letter[j] + 1, search = TRUE
; k < 26 && search
; k++ ) {
if ( Letter2Numeral[k] == PhoneNum[j] ) {
search = FALSE ;
found_one = TRUE ;
fprintf( stdout, " %c", (char)(k+'a') ) ;
digit_letter[j] = k ;
}
}
if ( search ) {
/* no further match found */
if ( digit_letter[j] < 0 ) {
/* numeral is not mapped, so output it directly */
fprintf( stdout, " %c", PhoneStr[j] ) ;
}
digit_letter[j] = 26 ;
}
}
}
}
fprintf( stdout, "\n" ) ;
}
}
void
concat_it()
{
int i, j, tot ;
char full_string[MAX_DIGITS+1] ;
for ( i = 0 ; i < NumDigits ; i++ ) {
if ( PhoneNum[i] == FIXED_LETTER ) {
OutputGrid[i][0] = PhoneStr[i] ;
OutputGrid[i][1] = '\0' ;
} else {
tot = 0 ;
for ( j = 0 ; j < 26 ; j++ ) {
if ( Letter2Numeral[j] == PhoneNum[i] ) {
OutputGrid[i][tot++] = (char)(j+'a') ;
}
}
if ( !tot ) {
/* no match found */
OutputGrid[i][tot++] = PhoneStr[i] ;
}
OutputGrid[i][tot] = '\0' ;
}
}
if ( Concat == 1 ) {
concat_letter_out( 0, full_string ) ;
} else {
concat_letter_breaks_out( 0, full_string ) ;
}
}
void
concat_letter_out( digit, full_string )
int digit ;
char *full_string ;
{
int i, length ;
char *cstr ;
if ( digit >= NumDigits ) {
full_string[digit] = '\0' ;
fprintf( stdout, "%s\n", full_string ) ;
} else {
length = strlen( cstr = OutputGrid[digit] ) ;
for ( i = 0 ; i < length ; i++ ) {
full_string[digit] = *cstr++ ;
concat_letter_out( digit+1, full_string ) ;
}
}
}
void
concat_letter_breaks_out( digit, full_string )
int digit ;
char *full_string ;
{
char brk_string[MAX_DIGITS*2] ;
int i, j, bny, index, length ;
char *cstr ;
if ( digit >= NumDigits ) {
if ( TotBrk == -1 ) {
TotBrk = 1 ;
for ( i = 1 ; i < NumDigits ; i++ ) {
TotBrk *= 2 ;
}
}
for ( i = 0 ; i < TotBrk ; i++ ) {
bny = i ;
index = 0 ;
for ( j = 0 ; j < NumDigits ; j++ ) {
brk_string[index++] = full_string[j] ;
if ( bny & 0x1 ) {
brk_string[index++] = ' ' ;
}
bny = bny >> 1 ;
}
brk_string[index] = '\0' ;
fprintf( stdout, "%s\n", brk_string ) ;
}
} else {
length = strlen( cstr = OutputGrid[digit] ) ;
for ( i = 0 ; i < length ; i++ ) {
full_string[digit] = *cstr++ ;
concat_letter_breaks_out( digit+1, full_string ) ;
}
}
}
/* create structures needed for the word list, etc */
void
init_wl()
{
p_wordlist p_wl ;
int i, j, length, search ;
char tstr[2] ;
for ( i = 0, p_wl = WL ; i < NumIndices ; i++, p_wl++ ) {
p_wl->p_word = NULL ;
p_wl->count = 0 ;
p_wl->size = 0 ;
}
/* figure out which numerals don't have any letter translations */
for ( i = 0 ; i < 10 ; i++ ) {
for ( j = 0, search = TRUE ; j < 26 && search ; j++ ) {
if ( i == Letter2Numeral[j] ) {
search = FALSE ;
}
}
/* set to TRUE if numeral is mapped by something */
NumeralMapped[i] = !search ;
}
tstr[1] = '\0' ;
/* add one number values as possible */
/* we rely on the fact that the first word in the single letter word
* lists is actually a numeral, so change the following at your own
* peril.
*/
for ( i = 0 ; i < 10 ; i++ ) {
tstr[0] = (char)i + '0' ;
(void)fit_word( tstr, 1 ) ;
}
/* add one letter words as possible */
length = strlen( OneLetter ) ;
for ( i = 0 ; i < length ; i++ ) {
tstr[0] = OneLetter[i] ;
(void)fit_word( tstr, 1 ) ;
}
}
/* see if the word fits in the database anywhere */
int
fit_word( dict_word, min_length )
char *dict_word ;
int min_length ;
{
int length, compare_length, true_length, index_length, nl ;
int i, j ;
int word_val[MAX_DIGITS], hit[MAX_DIGITS], *wv, check_length, match, tot ;
char lc_dict_word[MAX_DIGITS], *wc, *lc, tchr, *cc ;
char clean_dict_word[BUFSIZE] ;
/* convert word to numbers */
length = strlen( dict_word ) ;
compare_length = true_length = 0 ;
for ( i = 0, wv = word_val, wc = dict_word, lc = lc_dict_word,
cc = clean_dict_word
; ( i < length ) && ( compare_length < NumDigits )
; i++, wc++ ) {
/* remove apostrophes, hyphens, etc for matching */
tchr = tolower(*wc) ;
if ( ( tchr >= 'a' ) && ( tchr <= 'z' ) ) {
*wv++ = Letter2Numeral[(*lc++ = tchr) -'a'] ;
compare_length++ ;
} else if ( ( tchr >= '0' ) && ( tchr <= '9' ) ) {
*wv++ = (*lc++ = tchr) -'0' ;
compare_length++ ;
}
/* clean the word of any carriage return junk */
if ( tchr > 13 ) {
*cc++ = *wc ;
}
}
true_length = compare_length ;
while ( *wc ) {
tchr = tolower( *wc++ ) ;
/* get true length of word in valid characters */
if ( ( tchr >= 'a' ) && ( tchr <= 'z' ) ) {
true_length++ ;
} else if ( ( tchr >= '0' ) && ( tchr <= '9' ) ) {
true_length++ ;
}
/* copy the rest of the word */
if ( tchr > 13 ) {
*cc++ = tchr ;
}
}
/* end the cleaned word */
*cc = '\0' ;
/* is the word too long? */
if ( true_length > NumDigits + Wildcard ) {
/* the word was too long */
return( 0 ) ;
}
/* is the word too short? */
if ( true_length < min_length ) {
/* the word was too short */
return( 0 ) ;
}
/* now look for matches */
if ( Wildcard ) {
check_length = NumDigits - true_length + Wildcard ;
if ( check_length >= NumDigits ) {
/* cannot index into array at higher than NumDigits-1, so reduce */
check_length = NumDigits - 1 ;
}
} else {
check_length = NumDigits - true_length ;
}
for ( i = 0, tot = 0 ; i <= check_length ; i++ ) {
index_length = compare_length+i ;
if ( Wildcard ) {
if ( index_length > NumDigits ) {
/* cut comparisons down to numerals available */
index_length = NumDigits ;
}
}
for ( j = i, wv = word_val, match = TRUE
; match && (j < index_length)
; j++, wv++ ) {
/* numerical match? */
if ( PhoneNum[j] != *wv ) {
/* no; exact letter match? */
if ( ( PhoneNum[j] != FIXED_LETTER ) ||
( PhoneStr[j] != lc_dict_word[j-i] ) ) {
/* no match, stop testing */
match = FALSE ;
}
}
}
if ( match ) {
/* word fits, store index */
hit[tot++] = i ;
}
}
/* were there any matches? */
if ( tot ) {
/* make one copy of the word */
wc = strdup( clean_dict_word ) ;
hold_word( wc ) ;
for ( i = 0 ; i < tot ; i++ ) {
if ( Wildcard ) {
if ( hit[i] + true_length <= NumDigits ) {
nl = true_length ;
} else {
nl = NumDigits - hit[i] ;
}
store_word( wc, hit[i], nl ) ;
} else {
store_word( wc, hit[i], true_length ) ;
}
}
}
return( tot ) ;
}
/* yeah, I could combine this with store_word - call me lazy... */
void
hold_word( word )
char *word ;
{
if ( HoldSize <= HoldCount ) {
if ( HoldSize ) {
HoldSize += WORD_LIST_SIZE * NumDigits ;
HoldWord = (char **)realloc( (void *)HoldWord,
HoldSize * sizeof(char *)) ;
} else {
HoldSize = WORD_LIST_SIZE * NumDigits ;
HoldWord =
(char **)malloc( HoldSize * sizeof(char *)) ;
}
if ( HoldWord == NULL ) {
fprintf( stderr, "Ugh, we're out of memory!\n" ) ;
exit(1) ;
}
}
HoldWord[HoldCount++] = word ;
}
/* store word in the given location */
void
store_word( word, digit, length )
char *word ;
int digit ;
int length ;
{
p_wordlist p_wl ;
p_wl = &WL[IndexWL( digit, length )] ;
/* check storage space */
if ( p_wl->size <= p_wl->count ) {
if ( p_wl->size ) {
p_wl->size += WORD_LIST_SIZE ;
p_wl->p_word = (char **)realloc( (void *)p_wl->p_word,
p_wl->size * sizeof(char *)) ;
} else {
p_wl->size = WORD_LIST_SIZE ;
p_wl->p_word =
(char **)malloc( p_wl->size * sizeof(char *)) ;
}
if ( p_wl->p_word == NULL ) {
fprintf( stderr, "Ugh, we're out of memory!\n" ) ;
exit(1) ;
}
}
/* store word in structure */
p_wl->p_word[p_wl->count++] = word ;
}
/* search through the stored words for matches */
void
search_for_match( digit, full_string, suffix_loc, numeral_count )
int digit ;
char *full_string ;
char *suffix_loc ;
int numeral_count ;
{
int length, tot_len, tot_word, wn, add_num, add_val ;
p_wordlist p_wl ;
char **p_word ;
tot_len = NumDigits - digit ;
/* loop through all possible word lengths from this point */
/* count down so that the longer strings are output first */
for ( length = tot_len ; length > 0 ; length-- ) {
p_wl = &WL[IndexWL( digit, length )] ;
tot_word = p_wl->count ;
/* now go through all words on the list */
if ( length == 1 ) {
/* is the numeral of the first word mapped? */
if ( NumeralMapped[**(p_wl->p_word)-'0'] ) {
/* don't include first word (a mapped numeral) if we've used
* up our quota.
*/
wn = (numeral_count >= NumNumerals ) ;
add_num = 1 ;
} else {
/* an unmapped numeral, so definitely do it */
wn = 0 ;
add_num = 0 ;
}
} else {
/* not on the one letter word list, so do all words */
wn = 0 ;
add_num = 0 ;
}
for ( p_word = p_wl->p_word + wn
; wn < tot_word
; wn++, p_word++ ) {
strcpy( suffix_loc, *p_word ) ;
if ( length == tot_len ) {
/* finished - output it! */
fprintf( stdout, "%s\n", full_string ) ;
MatchTot++ ;
} else {
strcat( suffix_loc, " " ) ;
/* Add one to numeral_count only if numeral is used */
search_for_match( digit+length, full_string,
suffix_loc + strlen( suffix_loc ),
numeral_count + add_num ) ;
}
}
}
}
void
free_wl()
{
int i ;
p_wordlist p_wl ;
for ( i = 0, p_wl = WL ; i < NumIndices ; i++, p_wl++ ) {
if ( p_wl->size ) {
p_wl->size = 0 ;
p_wl->count = 0 ;
free( p_wl->p_word ) ;
}
}
/* the only function of HoldWord is to be able to free the word memory */
if ( HoldSize ) {
for ( i = 0 ; i < HoldCount ; i++ ) {
free( HoldWord[i] ) ;
}
free( HoldWord ) ;
}
HoldCount = HoldSize = 0 ;
}
/* strip out all valid "-" arguments and their values */
int
scan_options( argc, argv, nargc, nargv )
int argc ;
char *argv[] ;
int *nargc ;
char *nargv[] ;
{
int num_arg ;
int i ;
char str[BUFSIZE] ;
*nargc = num_arg = 0 ;
while ( ++num_arg < argc ) {
if ( *argv[num_arg] == '-' ) {
switch( argv[num_arg][1] ) {
case 'l': /* minimum length of words */
if ( ++num_arg < argc ) {
sscanf( argv[num_arg], "%d", &i ) ;
if ( i < 1 ) {
fprintf( stderr,
"Minimum word length too low!\n" ) ;
USAGE ;
return( FALSE ) ;
}
MinLength = i ;
}
break ;
case 'n': /* number of numerals allowed */
if ( ++num_arg < argc ) {
sscanf( argv[num_arg], "%d", &i ) ;
if ( i < 0 ) {
fprintf( stderr, "Number of numerals too low!\n" ) ;
USAGE ;
return( FALSE ) ;
}
NumNumerals = i ;
}
break ;
case 'q': /* mapping of q */
if ( ++num_arg < argc ) {
sscanf( argv[num_arg], "%d", &i ) ;
if ( (i >= 0) && (i <= 9) ) {
Letter2Numeral['q'-'a'] = i ;
}
}
break ;
case 'z': /* mapping of z */
if ( ++num_arg < argc ) {
sscanf( argv[num_arg], "%d", &i ) ;
if ( (i >= 0) && (i <= 9) ) {
Letter2Numeral['z'-'a'] = i ;
}
}
break ;
case 'd': /* dictionary path */
if ( ++num_arg < argc ) {
sscanf( argv[num_arg], "%s", DictPath ) ;
}
break ;
case 's': /* allowed single letter words */
if ( ++num_arg < argc ) {
sscanf( argv[num_arg], "%s", OneLetter ) ;
}
break ;
case 'm': /* mapping of entire alphabet */
if ( ++num_arg < argc ) {
sscanf( argv[num_arg], "%s", str ) ;
if ( strlen(str) != 26 ) {
fprintf( stderr, "Must input all 26 digits\n" ) ;
USAGE ;
return( FALSE ) ;
}
for ( i = 0 ; i < 26 ; i++ ) {
if ( (str[i] >= '0') && (str[i] <= '9') ) {
Letter2Numeral[i] = str[i] - '0' ;
} else {
Letter2Numeral[i] = NO_NUMBER ;
}
}
if ( Verbose ) {
fprintf( stderr, "here's your banana: )\n" ) ;
}
}
break ;
case 'r': /* output concatenation */
RollOwn = TRUE ;
break ;
case 'c': /* output concatenation */
Concat = 1 ;
break ;
case 'C': /* output spacing & concatenation */
Concat = 2 ;
break ;
case 'v': /* verbose output */
Verbose = TRUE ;
break ;
default:
fprintf( stderr, "No such option `-%c'\n",
argv[num_arg][1] ) ;
USAGE ;
return( FALSE ) ;
}
} else {
/* not an argument, so pass it on */
nargv[(*nargc)++] = argv[num_arg] ;
}
}
return( TRUE ) ;
}